package cn.b.sky.user.controller;

import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.enums.ParameterEnums;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.common.model.BatchJobReport;
import cn.b.sky.common.model.DWZResult;
import cn.b.sky.common.utils.EncryptAlgorithm;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.user.enums.ECodeEnums;
import cn.b.sky.user.service.*;
import cn.b.sky.user.service.model.*;
import cn.b.sky.user.service.model.condition.RoleCondition;
import cn.b.sky.user.service.model.condition.UserCondition;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 
 * @ClassName: UserController
 * @Description:用户管理控制器
 * @author: ZhaoXin
 * @date: 2015-7-31 下午01:17:26
 * @version: V1.0
 * 
 */
@Controller
@RequestMapping(value = "/user/*")
@Slf4j
public class UserController extends SecurityController {

  @Resource
  UserService userService;

  @Resource
  OrganizationService organizationService;

  @Resource
  private ECodeService eCodeService;

  @Resource
  RoleService roleService;

  @Resource
  ParameterService parameterService;

  @Autowired
  PasswordEncoder passwordEncoder;

  @RequestMapping("userList")
  public String userList(Model model, @ModelAttribute("condition") UserCondition user, String navTabId) {
    user.setLanguageCode(SecurityContextUtil.getLanguageCode());
    user.seteCodeType(ECodeEnums.USERTYPE.getCode());
    user.setSiteCode(SecurityContextUtil.getSiteCode());
    List<UserInfo> users = userService.selectUserList(user);
    int count = userService.selectUserListCount(user);
    List<ECode> types = eCodeService.selectECodeList(ECodeEnums.USERTYPE.getCode(),
        SecurityContextUtil.getLanguageCode());
    user.setData(users);
    user.setTotalCount(count);
    model.addAttribute("page", user);
    model.addAttribute(NAVTABID, navTabId);
    model.addAttribute("userType", types);
    return "user/user_list";
  }

  @RequestMapping("userLookUp")
  public String userLookUp(Model model, @ModelAttribute("condition") UserCondition user, String navTabId) {
    user.setLanguageCode(SecurityContextUtil.getLanguageCode());
    user.seteCodeType(ECodeEnums.USERTYPE.getCode());
    user.setSiteCode(SecurityContextUtil.getSiteCode());
    List<UserInfo> users = userService.selectUserList(user);
    int count = userService.selectUserListCount(user);
    List<ECode> types = eCodeService.selectECodeList(ECodeEnums.USERTYPE.getCode(),
        SecurityContextUtil.getLanguageCode());
    user.setData(users);
    user.setTotalCount(count);
    model.addAttribute("page", user);
    model.addAttribute(NAVTABID, navTabId);
    model.addAttribute("userType", types);
    return "user/user_lookup";
  }
  
  @RequestMapping("addUser")
  public String addUser(Model model, String navTabId) {
    model.addAttribute(NAVTABID, navTabId);
    List<ECode> types = eCodeService.selectECodeList(ECodeEnums.USERTYPE.getCode(),
        SecurityContextUtil.getLanguageCode());
    List<Language> languages = userService.selectAllLanaguage();
    List<TimeZone> timezones = userService.selectTimeZone();
    model.addAttribute("userType", types);
    model.addAttribute("languages", languages);
    model.addAttribute("timezones", timezones);
    return "user/user_add";
  }

  @RequestMapping("selectOrg")
  public String selectOrg(Model model, String navTabId) {
    model.addAttribute(NAVTABID, navTabId);
    List<Organization> orgs = organizationService.selectOrganizationList(SecurityContextUtil.getSiteCode(), false);

    model.addAttribute("treeList", orgs);
    return "user/org_select";
  }

  @RequestMapping("selectRole")
  public String selectRole(Model model, @ModelAttribute("condition") RoleCondition role, String navTabId) {
    role.setSiteCode(SecurityContextUtil.getSiteCode());
    role.setLockFlag(0);
    List<Role> roles = roleService.selectRoleList(role);
    int count = roleService.selectRoleCount(role);
    role.setData(roles);
    role.setTotalCount(count);
    model.addAttribute("page", role);
    model.addAttribute(NAVTABID, navTabId);
    return "user/role_select";
  }

  @RequestMapping("saveUser")
  @ResponseBody
  public DWZResult saveUser(Model model, String navTabId, String id, UserInfo user, String org, String role,
                            HttpServletRequest request) {
    if (user == null) {
      return ajaxError(getImeViewMessageI18n(null, SystemConstant.PARAMETERNULL));
    }
    try {
      // 处理用户信息
      user.setSiteCode(SecurityContextUtil.getSiteCode());
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      if (!StringUtils.isEmpty(user.getFromDateStr())) {
        Date date = sdf.parse(user.getFromDateStr());
        user.setFromDate(date);
      }
      if (!StringUtils.isEmpty(user.getToDateStr())) {
        Date date = sdf.parse(user.getToDateStr());
        user.setToDate(date);
      }
      if (!StringUtils.isEmpty(user.getBirthDateStr())) {
        Date date = sdf.parse(user.getBirthDateStr());
        user.setBirthDate(date);
      }
      if (user.getSystemFlag() == null) {
        user.setSystemFlag(0);
      }
      // 处理用户组织
      if (!StringUtils.isEmpty(org)) {
        List<UserOrganization> orgList = new ArrayList<UserOrganization>();
        String[] orgs = org.split(",");
        for (String s : orgs) {
          UserOrganization o = new UserOrganization();
          o.setSiteCode(SecurityContextUtil.getSiteCode());
          o.setUserCode(user.getUserCode());
          o.setOrganizationCode(s);
          setCreateInfo(o);
          orgList.add(o);
        }
        user.setOrgList(orgList);
      }
      // 处理角色
      if (!StringUtils.isEmpty(role)) {
        List<UserRole> roleList = new ArrayList<UserRole>();
        String[] roles = role.split(",");
        for (String s : roles) {
          UserRole o = new UserRole();
          o.setSiteCode(SecurityContextUtil.getSiteCode());
          o.setUserCode(user.getUserCode());
          o.setRoleCode(s);
          setCreateInfo(o);
          roleList.add(o);
        }
        user.setRoleList(roleList);
      }
      setCreateInfo(user);
      if (StringUtils.isEmpty(id)) {
        user.setPassword(passwordEncoder.encode(getPassword()));
        user.setUsername(user.getUserCode() + "@" + SecurityContextUtil.getSiteCode());
        userService.insertUser(user);
        String forwardUrl = getForwardUrl(request) + "/user/userList?navTabId=" + navTabId;
        return dialogAjaxDone(getImeViewMessageI18n(null, "successfulOperation.M"), navTabId, null, forwardUrl, null);
      } else {
        userService.updateUser(user);
        return dialogAjaxDone(getImeViewMessageI18n(null, "successfulOperation.M"), null, null, null, null);
      }

    } catch (ImeException e) {
      throw e;
    } catch (Exception e) {
      log.error("{}", e);
      model.addAttribute("message", e.getMessage());
      return ajaxError(getImeViewMessageI18n(null, "failedOperation.M"));
    }

  }

  @RequestMapping("modifyUser")
  public String modifyResource(Model model, String navTabId, String id) {
    UserInfo user = userService.selectUser(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute(NAVTABID, navTabId);
    model.addAttribute("user", user);
    List<ECode> types = eCodeService.selectECodeList(ECodeEnums.USERTYPE.getCode(),
        SecurityContextUtil.getLanguageCode());
    List<Language> languages = userService.selectAllLanaguage();
    List<TimeZone> timezones = userService.selectTimeZone();
    model.addAttribute("userType", types);
    model.addAttribute("languages", languages);
    model.addAttribute("timezones", timezones);
    List<Organization> orgs = userService.selectOrganizationByUser(SecurityContextUtil.getSiteCode(), id);
    List<Organization> os = organizationService.selectOrganizationList(SecurityContextUtil.getSiteCode(), true);
    for (Organization o : orgs) {
      Organization ol = findOrganization(os, o);
      o.setPath(ol.getPath());
    }

    model.addAttribute("orgs", orgs);
    List<Role> roles = userService.selectRoleByUser(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute("roles", roles);
    List<UserParameter> paras = userService.selectUserParameter(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute("paras", paras);
    return "user/user_add";
  }

  private Organization findOrganization(List<Organization> os, Organization org) {
    Organization o = null;
    boolean isFind = false;
    for (Organization ol : os) {
      if (org.getOrganizationCode().equals(ol.getOrganizationCode())) {
        o = ol;
        isFind = true;
      }
    }
    if (!isFind) {
      for (Organization ol : os) {
        o = findOrganization(ol.getChildren(), org);
        if (o != null) {
          break;
        }
      }
    }
    return o;
  }

  /**
   * 
   * <strong>Title : validateUserCode<br></strong>
   * <strong>Description : </strong>新增的时候校验是否已经存在，存在返回false<br> 
   * <strong>Create on : 2016-11-1 上午10:06:41<br></strong>
   * <p>
   * @param userCode
   * @param model
   * @return
   * boolean
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  @RequestMapping("checkedUserCodeExits")
  @ResponseBody
  public boolean checkedUserCodeExits(String userCode, Model model) {
    if (!StringUtils.isEmpty(userCode)) {
      UserInfo user = userService.selectUser(getSiteCode(), userCode);
      if(user != null){
        return false;
      }
    }
    return true;
  }
  
  /**
   * 
   * <strong>Title : validateUserCode<br></strong>
   * <strong>Description : </strong>选择用户时校验用户是否存在，不存在返回false<br> 
   * <strong>Create on : 2016-11-1 上午10:08:20<br></strong>
   * <p>
   * @param userCode
   * @param model
   * @return
   * boolean
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  @RequestMapping("checkedUserCodeNotExits")
  @ResponseBody
  public boolean checkedUserCodeNotExits(String userCode, Model model) {
    if (!StringUtils.isEmpty(userCode)) {
      UserInfo user = userService.selectUser(getSiteCode(), userCode);
      if(user != null && user.getLockFlag() == 0){
        return true;
      }
    }
    return false;
  }

  @RequestMapping("viewUser")
  public String viewUser(Model model, String navTabId, String id) {
    UserInfo user = userService.selectUser(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute(NAVTABID, navTabId);
    model.addAttribute("user", user);
    List<ECode> types = eCodeService.selectECodeList(ECodeEnums.USERTYPE.getCode(),
        SecurityContextUtil.getLanguageCode());
    List<Language> languages = userService.selectAllLanaguage();
    List<TimeZone> timezones = userService.selectTimeZone();
    model.addAttribute("userType", types);
    model.addAttribute("languages", languages);
    model.addAttribute("timezones", timezones);
    List<Organization> orgs = userService.selectOrganizationByUser(SecurityContextUtil.getSiteCode(), id);
    List<Organization> os = organizationService.selectOrganizationList(SecurityContextUtil.getSiteCode(), false);
    for (Organization o : orgs) {
      Organization ol = findOrganization(os, o);
      o.setPath(ol.getPath());
    }

    model.addAttribute("orgs", orgs);
    List<Role> roles = userService.selectRoleByUser(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute("roles", roles);
    List<UserParameter> paras = userService.selectUserParameter(SecurityContextUtil.getSiteCode(), id);
    model.addAttribute("paras", paras);
    return "user/user_view";
  }

  @RequestMapping("deleteUser")
  @ResponseBody
  public DWZResult deleteUser(Model model, String navTabId, HttpServletRequest request) {
    String ids = request.getParameter("ids");
    if (StringUtils.isEmpty(ids)) {
      return ajaxError(getImeViewMessageI18n(null, SystemConstant.PARAMETERNULL));
    }
    String[] ress = ids.split(",");
    List<BatchJobReport> reports = new ArrayList<BatchJobReport>(ress.length);
    boolean hasFail = false;
    for (String res : ress) {
      BatchJobReport report = userService.deleteUser(getSiteCode(), res);
      reports.add(report);
      if (!report.isSuccess()) {
        hasFail = true;
      }
    }
    if (!hasFail) {
      // 直接返回成功消息
      return navTabAjaxDone(navTabId, null, null, null, getImeViewMessageI18n(null, "successfulOperation.M"), null);
    } else {
      return batchjobAjaxDone(request, reports);
    }

  }

  @RequestMapping("savePwd")
  @ResponseBody
  public DWZResult savePwd(Model model, String navTabId, UserInfo user, HttpServletRequest request) {
    try {
      if (user == null) {
        return ajaxError(getImeViewMessageI18n(null, SystemConstant.PARAMETERNULL));
      }
      UserInfo u = userService.selectUser(SecurityContextUtil.getSiteCode(), SecurityContextUtil.getCurrentUserName());
      if ( passwordEncoder.encode(user.getPassword()).equals(u.getPassword())) {
        if (user.getPassword().equals(user.getNewPassword())) {
          return ajaxError(getImeViewMessageI18n(null, "newPasswordError.M"));
        }
        userService.updateUserPwd(SecurityContextUtil.getSiteCode(), SecurityContextUtil.getCurrentUserName(),
                passwordEncoder.encode(user.getNewPassword()));
        return dialogAjaxDone(getImeViewMessageI18n(null, "successfulOperation.M"), navTabId, null, null, null);
      } else {
        return ajaxError(getImeViewMessageI18n(null, "oldPasswordError.M"));
      }
    } catch (Exception e) {
      log.error("{}", e);
      model.addAttribute("message", e.getMessage());
      return ajaxError(getImeViewMessageI18n(null, "failedOperation.M"));
    }
  }

  @RequestMapping("changePwd")
  public String changePwd(Model model, String navTabId) {
    model.addAttribute(NAVTABID, navTabId);
    return "user/changepwd";
  }

  /**
   * 
   * <strong>Title : flowNodeUserLookUp<br></strong>
   * <strong>Description : </strong>流程分配用户，<br> 
   * <strong>Create on : 2015-11-23 上午10:20:24<br></strong>
   * <p>
   * @param model
   * @param user
   * @return
   * String
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  @RequestMapping({ "flowNodeUserLookUp" })
  public String flowNodeUserLookUp(Model model, @ModelAttribute("condition") UserCondition user) {
    user.setLanguageCode(SecurityContextUtil.getLanguageCode());
    user.seteCodeType(ECodeEnums.USERTYPE.getCode());
    user.setSiteCode(SecurityContextUtil.getSiteCode());
    List<UserInfo> users = this.userService.selectUserList(user);
    int count = this.userService.selectUserListCount(user);
    user.setData(users);
    user.setTotalCount(count);
    model.addAttribute("page", user);
    return "engine/flownode/flowNodeUserLookUp";
  }

  @RequestMapping({ "userSuggest" })
  @ResponseBody
  public Object flowNodeUserSuggest(@ModelAttribute("condition") UserCondition user) {
    user.setLanguageCode(SecurityContextUtil.getLanguageCode());
    user.seteCodeType(ECodeEnums.USERTYPE.getCode());
    user.setSiteCode(SecurityContextUtil.getSiteCode());
    user.setLockFlag(0);
    return userService.selectUserSuggests(user);
  }

  /**
   * 
   * <strong>Title : getPassword<br></strong>
   * <strong>Description : </strong>获取初始密码<br> 
   * <strong>Create on : 2016年5月4日 下午2:52:15<br></strong>
   * <p>
   * @return
   * String
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  private String getPassword() {
    ParameterEntity pe = parameterService.getParameterEntityByCode(ParameterEnums.DEFAULTPASSWORD.getCode(), getSiteCode());
    if (null != pe && !StringUtils.isBlank(pe.getDefaultValue())) {
      return pe.getDefaultValue();
    }
      return "a123456";
  }

  @RequestMapping("resetPassword")
  @ResponseBody
  public DWZResult resetPassword(Model model, String navTabId, HttpServletRequest request) {
    String ids = request.getParameter("ids");
    if (StringUtils.isEmpty(ids)) {
      return ajaxError(getImeViewMessageI18n(SecurityContextUtil.getLanguageCode(),
          SystemConstant.PARAMETERNULL));
    }
    String[] ress = ids.split(",");
    for (String res : ress) {
      userService.updateUserPwd(SecurityContextUtil.getSiteCode(), res, passwordEncoder.encode(getPassword()));
    }
    return navTabAjaxDone(navTabId, null, null, null, getImeViewMessageI18n(null, "successfulOperation.M"), null);

  }
}
